package CrowdCountingMVC.CCView.CCShow;

import Const.State;
import CrowdCounting.Model.AbstractComponentFactory;
import CrowdCounting.Model.ComponentFactoryImp.ComponentFactory;
import CrowdCounting.Model.CrowdCounting.CrowdCountingDisplayFrame;
import CrowdCounting.Model.Util;
import CrowdCountingMVC.CCControler.CrowdCountingControllerInerface;
import CrowdCountingMVC.CCModel.CrowdCountingModelInterface;
import CrowdCountingMVC.CCView.CCObserver.CrowdShowObserver;
import CrowdCountingMVC.CCView.CCObserver.PersonNumShowObserver;
import CrowdCountingMVC.CCView.CCObserver.WarningShowObserver;
import CrowdCountingMVC.ExceptionInfo.InputException;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.logging.Level;

public class CrowdCountingShow implements CrowdShowObserver, WarningShowObserver, PersonNumShowObserver {

    CrowdCountingModelInterface ccModel;
    CrowdCountingControllerInerface ccController;
    DisplayFrame displayFrame;

    private CrowdCountingDisplayFrame crowdCountingDisplayFrame;
    private JPanel contentPane;
    private JLabel warningImageLabel;
    private JLabel crowdImageLabel;
    private JLabel personNumTextLabel;
    private JLabel optErrorTextLabel;

    private JTextField segmentTextInput;
    private JTextField thresholdTextInput;

    private AbstractComponentFactory componentFactory;


    public CrowdCountingShow(CrowdCountingModelInterface model, CrowdCountingControllerInerface controller, int width, int height) {

        ccModel = model;
        ccController = controller;
        displayFrame = new DisplayFrame();

        componentFactory = new ComponentFactory();
        crowdCountingDisplayFrame = new CrowdCountingDisplayFrame("人群密度异常预警系统", width, height);
        contentPane = (JPanel) crowdCountingDisplayFrame.getContentPane();
        contentPane.setLayout(null);
        warningImageLabel = new JLabel();
        crowdImageLabel = new JLabel();
        personNumTextLabel = new JLabel("当前预测人数：--");

    }


    private void addFrameComponents() {

        JButton startButton = (JButton) componentFactory.getComponent(new JButton("Start"), 100, 50, 50, 25, Color.BLUE, 25);
        JButton stopButton = (JButton) componentFactory.getComponent(new JButton("Stop"), 100, 50, 150, 25, Color.MAGENTA, 25);
        JButton closeButton = (JButton) componentFactory.getComponent(new JButton("End"), 100, 50, 250, 25, Color.RED, 25);

        segmentTextInput = (JTextField) componentFactory.getComponent(new JTextField(), 80, 25, 140, 110, Color.BLACK, 20);
        segmentTextInput.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, true));
        JLabel segmentTextInputLabel = (JLabel) componentFactory.getComponent(new JLabel("分块尺度"), 100, 25, 45, 110, Color.BLACK, 20);

        thresholdTextInput = (JTextField) componentFactory.getComponent(new JTextField(), 80, 25, 140, 140, Color.BLACK, 20);
        thresholdTextInput.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, true));
        JLabel thresholdTextInputLabel = (JLabel) componentFactory.getComponent(new JLabel("子块阈值"), 100, 25, 45, 140, Color.BLACK, 20);


        JPanel warningImagePanel = componentFactory.getPaneDefault(500, 500, 650, 200);
        warningImageLabel = (JLabel) componentFactory.getComponent(warningImageLabel, 500, 500, 60, 20, null, 0);
        JLabel warningImageTextLabel = (JLabel) componentFactory.getComponent(new JLabel("预警图像"), 200, 30, 190, 20, Color.BLACK, 30);

        warningImagePanel.add(warningImageLabel);
        warningImagePanel.add(warningImageTextLabel);

        JPanel crowdImagePanel = componentFactory.getPaneDefault(500, 500, 50, 200);
        crowdImageLabel = (JLabel) componentFactory.getComponent(crowdImageLabel, 500, 500, 60, 20, null, 0);
        JLabel crowdImageTextLabel = (JLabel) componentFactory.getComponent(new JLabel("人群图像"), 200, 30, 190, 20, Color.BLACK, 30);

        crowdImagePanel.add(crowdImageLabel);
        crowdImagePanel.add(crowdImageTextLabel);


        personNumTextLabel = (JLabel) componentFactory.getComponent(personNumTextLabel, 300, 100, 500, 80, Color.BLACK, 35);
        optErrorTextLabel = (JLabel) componentFactory.getComponent(new JLabel(), 1000, 100, 500, 15, Color.RED, 40);

        startButton.addActionListener(e -> {
            startAction();
        });

        closeButton.addActionListener(e -> {
            endAction();
        });

        stopButton.addActionListener(e -> {
            stopAction();
        });

        crowdCountingDisplayFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Util.logger(Level.INFO, "End");
                ccController.end();
            }
        });

        segmentTextInput.addActionListener(e -> {
            segmentTextInputAction();
        });

        thresholdTextInput.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                thresholdTextInputAction();
            }
        });


        contentPane.add(startButton);
        contentPane.add(closeButton);
        contentPane.add(stopButton);
        contentPane.add(warningImagePanel);
        contentPane.add(crowdImagePanel);
        contentPane.add(personNumTextLabel);
        contentPane.add(optErrorTextLabel);

        contentPane.add(segmentTextInput);
        contentPane.add(segmentTextInputLabel);
        contentPane.add(thresholdTextInput);
        contentPane.add(thresholdTextInputLabel);

    }

    private void startAction() {
        Util.logger(Level.INFO, "Start");
        if(ccModel.getShowState() == State.CLOSE){
            warningImageLabel.setText("数据加载中请稍后......");
            warningImageLabel.setFont(new Font(null, Font.BOLD, 30));
            warningImageLabel.repaint();

            crowdImageLabel.setText("数据加载中请稍后......");
            crowdImageLabel.setFont(new Font(null, Font.BOLD, 30));
            crowdImageLabel.repaint();

        }

        try {
            ccController.start();
        } catch (InputException e) {
            showWarningText(e.getMessage());
        }
    }

    private void endAction() {
        Util.logger(Level.INFO, "End");
        ccController.end();
        segmentTextInput.setForeground(Color.BLACK);
        thresholdTextInput.setForeground(Color.BLACK);
        Util.sleepTime(1000);
        warningImageLabel.setIcon(null);
        crowdImageLabel.setIcon(null);
        personNumTextLabel.setText("当前预测人数：--");
    }

    private void stopAction() {
        Util.logger(Level.INFO, "Stop");
        ccController.stop();
    }

    private void segmentTextInputAction() {
        String input = segmentTextInput.getText();
        try {
            ccController.inputSegmentParam(input);
            segmentTextInput.setForeground(Color.GRAY);
        } catch (InputException e) {
            showWarningText(e.getMessage());
        }

    }

    private void thresholdTextInputAction() {
        String input = thresholdTextInput.getText();
        try {
            ccController.inputThresholdParam(input);
            thresholdTextInput.setForeground(Color.GRAY);
        } catch (InputException e) {
            showWarningText(e.getMessage());
        }
    }

    public void showWarningText(String warningText) {
        optErrorTextLabel.setText(warningText);
        optErrorTextLabel.setVisible(true);
        Timer warningTimer = new Timer(2000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                optErrorTextLabel.setVisible(false);
            }
        });
        warningTimer.setRepeats(false);
        warningTimer.start();
    }

    public void showCrowdCounting() {
        addFrameComponents();
        crowdCountingDisplayFrame.setVisible(true);
    }

    @Override
    public void updateCrowdShow() {
        displayFrame.displayImage(crowdImageLabel, ccModel.getCrowdImageFile());
    }

    @Override
    public void updateWarningShow() {
        displayFrame.displayImage(warningImageLabel, ccModel.getWarningImageFile());
    }

    @Override
    public void updatePersonNumShow() {
        displayFrame.displayText(personNumTextLabel, ccModel.getPersonNumText());
    }
}
